home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1980 Regents of the University of California.
- * All rights reserved. The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
- */
-
- #ifndef lint
- static char *sccsid = "@(#)ex_unix.c 7.7 (Berkeley) 3/9/87; 1.6 (Bellcore) 87/07/09";
- #endif not lint
-
- #include "ex.h"
- #include "ex_temp.h"
- #include "ex_tty.h"
- #include "ex_vis.h"
-
- /*
- * Unix escapes, filtering
- */
-
- /*
- * First part of a shell escape,
- * parse the line, expanding # and % and ! and printing if implied.
- */
- unix0(warn)
- bool warn;
- {
- register char *up, *fp;
- register short c;
- char printub, puxb[UXBSIZE + sizeof (int)];
-
- printub = 0;
- CP(puxb, uxb);
- c = ex_getchar();
- if (c == '\n' || c == EOF)
- error("Incomplete shell escape command@- use 'shell' to get a shell");
- up = uxb;
- do {
- switch (c) {
-
- case '\\':
- if (any(peekchar(), "%#!"))
- c = ex_getchar();
- default:
- if (up >= &uxb[UXBSIZE]) {
- tunix:
- uxb[0] = 0;
- error("Command too long");
- }
- *up++ = c;
- break;
-
- case '!':
- fp = puxb;
- if (*fp == 0) {
- uxb[0] = 0;
- error("No previous command@to substitute for !");
- }
- printub++;
- while (*fp) {
- if (up >= &uxb[UXBSIZE])
- goto tunix;
- *up++ = *fp++;
- }
- break;
-
- case '#':
- fp = altfile;
- if (*fp == 0) {
- uxb[0] = 0;
- error("No alternate filename@to substitute for #");
- }
- goto uexp;
-
- case '%':
- fp = savedfile;
- if (*fp == 0) {
- uxb[0] = 0;
- error("No filename@to substitute for %%");
- }
- uexp:
- printub++;
- while (*fp) {
- if (up >= &uxb[UXBSIZE])
- goto tunix;
- *up++ = *fp++ | QUOTE;
- }
- break;
- }
- c = ex_getchar();
- } while (c == '"' || c == '|' || !endcmd(c));
- if (c == EOF)
- ungetchar(c);
- *up = 0;
- if (!inopen)
- resetflav();
- if (warn)
- ckaw();
- if (warn && hush == 0 && chng && xchng != chng && value(WARN) && dol > zero) {
- xchng = chng;
- vnfl();
- ex_printf(mesg("[No write]|[No write since last change]"));
- noonl();
- flush();
- } else
- warn = 0;
- if (printub) {
- if (uxb[0] == 0)
- error("No previous command@to repeat");
- if (inopen) {
- splitw++;
- vclean();
- vgoto(WECHO, 0);
- }
- if (warn)
- vnfl();
- if (hush == 0)
- lprintf("!%s", uxb);
- if (inopen && Outchar != termchar) {
- vclreol();
- vgoto(WECHO, 0);
- } else
- putnl();
- flush();
- }
- }
-
- /*
- * Do the real work for execution of a shell escape.
- * Mode is like the number passed to open system calls
- * and indicates filtering. If input is implied, newstdin
- * must have been setup already.
- */
- ttymode
- unixex(opt, up, newstdin, mode)
- char *opt, *up;
- int newstdin, mode;
- {
- int pvec[2];
- ttymode f;
- register char *p;
- char suxb[UXBSIZE + sizeof(int)];
-
- signal(SIGINT, SIG_IGN);
- #ifdef SIGTSTP
- if (dosusp)
- signal(SIGTSTP, SIG_DFL);
- #endif
- if (inopen)
- f = setty(normf);
- if ((mode & 1) && pipe(pvec) < 0) {
- /* Newstdin should be io so it will be closed */
- if (inopen)
- ignore(setty(f));
- error("Can't make pipe for filter");
- }
- /*
- * Some SHELLs don't strip the 8th bit, so do it here.
- */
- if (up) {
- for (p = suxb; *up && p < &suxb[UXBSIZE]; p++, up++)
- *p = *up & TRIM;
- *p = 0;
- up = suxb;
- }
- #ifndef VFORK
- pid = fork();
- #else
- pid = vfork();
- #endif
- if (pid < 0) {
- if (mode & 1) {
- close(pvec[0]);
- close(pvec[1]);
- }
- setrupt();
- error("No more processes");
- }
- if (pid == 0) {
- if (mode & 2) {
- close(0);
- dup(newstdin);
- close(newstdin);
- }
- if (mode & 1) {
- close(pvec[0]);
- close(1);
- dup(pvec[1]);
- if (inopen) {
- close(2);
- dup(1);
- }
- close(pvec[1]);
- }
- if (io)
- close(io);
- if (tfile)
- close(tfile);
- #ifdef EXSTRINGS
- close(erfile);
- #endif
- signal(SIGHUP, oldhup);
- signal(SIGQUIT, oldquit);
- if (ruptible)
- signal(SIGINT, SIG_DFL);
- execl(svalue(SHELL), "sh", opt, up, (char *) 0);
- ex_printf("No %s!\n", svalue(SHELL));
- error(NOSTR);
- }
- if (mode & 1) {
- io = pvec[0];
- close(pvec[1]);
- }
- if (newstdin)
- close(newstdin);
- return (f);
- }
-
- /*
- * Wait for the command to complete.
- * F is for restoration of tty mode if from open/visual.
- * C flags suppression of printing.
- */
- unixwt(c, f)
- bool c;
- ttymode f;
- {
-
- waitfor();
- #ifdef SIGTSTP
- if (dosusp)
- signal(SIGTSTP, onsusp);
- #endif
- if (inopen)
- ignore(setty(f));
- setrupt();
- if (!inopen && c && hush == 0) {
- ex_printf("!\n");
- flush();
- termreset();
- gettmode();
- }
- }
-
- /*
- * Setup a pipeline for the filtration implied by mode
- * which is like a open number. If input is required to
- * the filter, then a child editor is created to write it.
- * If output is catch it from io which is created by unixex.
- */
- filter(mode)
- register int mode;
- {
- static int pvec[2];
- ttymode f; /* mjm: was register */
- register int lines = lineDOL();
- struct stat statb;
-
- mode++;
- if (mode & 2) {
- signal(SIGINT, SIG_IGN);
- if (pipe(pvec) < 0)
- error("Can't make pipe");
- pid = fork();
- io = pvec[0];
- if (pid < 0) {
- setrupt();
- close(pvec[1]);
- error("No more processes");
- }
- if (pid == 0) {
- setrupt();
- io = pvec[1];
- close(pvec[0]);
- putfile(1);
- ex_exit(0);
- }
- close(pvec[1]);
- io = pvec[0];
- setrupt();
- }
- f = unixex("-c", uxb, (mode & 2) ? pvec[0] : 0, mode);
- if (mode == 3) {
- ex_delete(0);
- addr2 = addr1 - 1;
- }
- if (mode & 1) {
- if(FIXUNDO)
- undap1 = undap2 = addr2+1;
- if (fstat(io, &statb) < 0)
- bsize = LBSIZE;
- else {
- bsize = statb.st_blksize;
- if (bsize <= 0)
- bsize = LBSIZE;
- }
- ignore(append(getfile, addr2));
- #ifdef TRACE
- if (trace)
- vudump("after append in filter");
- #endif
- }
- close(io);
- io = -1;
- unixwt(!inopen, f);
- netchHAD(lines);
- }
-
- /*
- * Set up to do a recover, getting io to be a pipe from
- * the recover process.
- */
- recover()
- {
- static int pvec[2];
-
- if (pipe(pvec) < 0)
- error(" Can't make pipe for recovery");
- pid = fork();
- io = pvec[0];
- if (pid < 0) {
- close(pvec[1]);
- error(" Can't fork to execute recovery");
- }
- if (pid == 0) {
- close(2);
- dup(1);
- close(1);
- dup(pvec[1]);
- close(pvec[1]);
- execl(EXRECOVER, "exrecover", svalue(DIRECTORY), file, (char *) 0);
- close(1);
- dup(2);
- error(" No recovery routine");
- }
- close(pvec[1]);
- }
-
- /*
- * Wait for the process (pid an external) to complete.
- */
- waitfor()
- {
- int stat = 0;
-
- do {
- rpid = wait(&stat);
- if (rpid == pid)
- status = stat;
- } while (rpid != -1);
- status = (status >> 8) & 0377;
- }
-
- /*
- * The end of a recover operation. If the process
- * exits non-zero, force not edited; otherwise force
- * a write.
- */
- revocer()
- {
-
- waitfor();
- if (pid == rpid && status != 0)
- edited = 0;
- else
- change();
- }
-